package net.oschina.allchat.server.framework.core.config;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.util.Enumeration;
import java.util.Properties;

import net.oschina.allchat.server.framework.core.commons.utils.IoUtils;

public class LocalFileConfiguration implements IConfiguration {
	protected Properties properties;
	
	public LocalFileConfiguration(String sFile) {
		this(sFile, null);
	}
	
	public LocalFileConfiguration(String sFile, IConfiguration parent) {
		if (sFile == null)
			throw new IllegalArgumentException("null file");
		
		init(new File(sFile), parent);
	}
	
	public LocalFileConfiguration(File file) {
		init(file, null);
	}
	
	public LocalFileConfiguration(File file, IConfiguration parent) {
		init(file, parent);
	}
	
	protected void init(File file, IConfiguration parent) {
		if (file == null) {
			throw new IllegalArgumentException("null file");
		}
		
		if (!file.exists()) {
			throw new IllegalArgumentException(String.format("%s doesn't exist", file.getPath()));
		}
		
		if (file.isDirectory()) {
			throw new IllegalArgumentException(String.format("%s is a directory", file.getPath()));
		}
		
		properties = new Properties();
		
		if (parent != null) {
			cloneParentProperties(parent);
		}
		
		Reader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			properties.load(reader);
			for (Object key : properties.keySet()) {
				if (key instanceof String) {
					String sKey = (String)key;
					if (sKey.startsWith("#")) {
						properties.remove(sKey);
					}
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(String.format("can't load configuration from file %s",
					file.getPath()), e);
		} finally {
			IoUtils.closeIO(reader);
		}
	}
	
	private void cloneParentProperties(IConfiguration parent) {
		for (String key : parent.keys()) {
			properties.put(key, parent.getString(key));
		}
	}
	
	@Override
	public Boolean getBoolean(String key) {
		return getBoolean(key, null);
	}

	@Override
	public Boolean getBoolean(String key, Boolean defaultValue) {
		String sValue = getString(key);
		if (sValue == null)
			return defaultValue;
		
		return Boolean.valueOf(sValue);
	}

	@Override
	public Integer getInteger(String key) {
		return getInteger(key, null);
	}

	@Override
	public Integer getInteger(String key, Integer defaultValue) {
		String sValue = getString(key);
		if (sValue == null)
			return defaultValue;
		
		return Integer.valueOf(sValue);
	}

	@Override
	public String getString(String key) {
		return getString(key, null);
	}

	@Override
	public String getString(String key, String defaultValue) {
		String value = (String)properties.get(key);
		
		return value == null ? defaultValue : value;
	}

	@Override
	public String[] keys() {
		String[] keys = new String[properties.size()];
		Enumeration<Object> eKeys = properties.keys();
		
		int i = 0;
		while (eKeys.hasMoreElements()) {
			Object key = eKeys.nextElement();
			keys[i] = (String)key;
			i++;
		}
		
		return keys;
	}

}
